package de.iplon.DataViewer;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class HttpSerie extends Serie {

	HttpSerie(String source, String SerieName){
		this.mSource = source;
		this.mSerieName = SerieName;
	}

	public void run(){
		// queries an http URL
		// if succesful, stores the Reply to String mRawdata
		String HttpReplyNew="";
		String inputLine;
		try{
		  URL url = new URL(mSource);
		  URLConnection yc = url.openConnection();
		  BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
		  
		  while ((inputLine = in.readLine()) != null) 
		      HttpReplyNew = HttpReplyNew + inputLine+ "\n";
		  in.close();
		  
		  HttpReplyNew = HttpReplyNew.trim();
		  this.mRawdata = HttpReplyNew;
		 /* Go on
		  */
		  if (!this.parseRawdata()) throw new Exception("parse error");
		  shiftTimeZone();
		  if (!this.createTimeSeries()) throw new Exception("error create timeSeries");
		  
		  mReady = true;
		} catch (Exception e) {
		  e.printStackTrace();
		  mReady = true;
		  mError = true;
		}            
	}
	
	protected boolean parseRawdata(){
	    /* 
	     * expected reply == "[{"timestamp":"1366353301","mValue":"4.9"},{"timestamp":"1366353604","mValue":"30.7"}]"
	     * parses mRawdata into resulting arrays:
	     * mTs[i] 		 mValue[i]  	
	     */
	     // delete all characters before the first occurence of '['
	     mRawdata.replaceFirst("^.*\\[", "[");
	     /*
	      * *** Find the corresponding closing bracket ****
	      * *** Find all positions of [inner] curly braces ***
	      * *** Ignore outer curly braces, if any	****
	      * method: openBraces  counter 
	      * http://stackoverflow.com/questions/524548/regular-expression-to-detect-semi-colon-terminated-c-for-while-loops/524624#524624
	      * preconditions:
	      * opening bracket at pos 0 [
	      * -- [nested] opening curly braces {
	      * -- -- {"strings" or "other characters" within curly braces}
	      * -- corresponding closing curly braces }
	      * closing bracket ]
	      */
	     int openBraces	=0; // level counter: {opening curly brace: openBraces++ ;  closing curly brace}: openBraces-- 
	     int pos		=1;
	     int posClosingDblQu;
	     // corresponging positions of opening and closing braces. Only inner braces.
	     int posOpenBr[] = new int[mRawdata.length()/2]; // max possible length needs
	     int posClosingBr[] = new int[mRawdata.length()/2]; // same length
	     int iBr = 0;	// counts all inner opening braces. 
	     
	     while (pos < mRawdata.length()) {
	  	   if (mRawdata.charAt(pos) == '{'){
	  		   openBraces++;
	  		   // overwrite position posOpenBr[iBr] if previous opening Brace had no closing counterpart
	  		   posOpenBr[iBr]=pos;
	  	   } else if (mRawdata.charAt(pos) == '"'){
	  		   pos++;
	  		   // jump to closing "  == next occurence of  "
	  		   posClosingDblQu = mRawdata.indexOf(('"'), pos);
	  		   if (posClosingDblQu > 0) {
	  			   pos = posClosingDblQu;
	  		   } else {
	  			   // error: missing closing DoubleQuote
	  			   pos = mRawdata.length()+100; // marks this error for later.
	  		   }
	  	   } else if (mRawdata.charAt(pos) == '}') {
	  		   openBraces--;
	  		   posClosingBr[iBr]=pos;
	  		   // increase [iBr] for next opening brace only if it's an inner brace (a direct counterpart to an open brace)
	  		   if (posOpenBr[iBr] != 0){
	  			   iBr++;
	  		   }
	  	   } else if (openBraces==0){
	  		   if (mRawdata.charAt(pos) == ']'){
	  			   // Closing bracket reached.
	  			   // cut all following text.			   
	  			   mRawdata = mRawdata.substring(1, pos++).trim();
	  		   } 
	  	   } 
	  	   pos++;
	     }
	     if (openBraces != 0){
	  	   // unbalanced braces {  }
	  	   mRawdata = "error in mRawdata: unbalanced braces{}";
	  	   return false;
	     } else if (pos==mRawdata.length()+101) {
	  	   mRawdata = "error in mRawdata: missing closing DoubleQuote";
	  	   return false;
	     }
	     /*
	      * parse pairs of timestamp and mValue:
	      * {"timestamp":"1366353301","mValue":"4.9"}
	      *  -------------------s------------------
	      *   --------sx[0]----------   ---sx[1]---
	      *               ----mTs----           -v-
	      */
	     String s;
	     this.mTs	  = new java.util.Date  [iBr]; // length of arrays as needed
	     this.mValue = new double [iBr];
	     iBr = 0;
	     // regex Pattern splits sx[0], sx[1]  each into two capturing groups
	     String regex = "\\\"(.*)\\\":\\\"(.*)\\\"";	   
	     Pattern pattern = Pattern.compile(regex);
	     while (posOpenBr[iBr]>0){
	  	   s  = mRawdata.substring(posOpenBr[iBr]++, posClosingBr[iBr]-1);
	  	   String[] sx = s.split(",");
	  	   // regex Pattern splits sx[0]  into two capturing groups: 
	  	   // 	matcher.group(1) == "timestamp" 
	  	   //   matcher.group(2) == "123123123" 
	         Matcher matcher = pattern.matcher(sx[0]);
	         if (matcher.find()){
	      	   if (matcher.group(1).equals("timestamp")){
	      		   // TODO String pruefen 
	      		   // allocate converted integer mValue 
	      		   this.mTs[iBr] = new java.util.Date(Long.parseLong(matcher.group(2))*1000);
	      	   }
	         } else {
	        	 // this timestamp is not valid
	        	 // this.mTs[iBr] == null;
	      	   continue;
	         }
	  	   // regex splits sx[1]  into two capturing groups: 
	  	   // 	matcher.group(1) == "mValue" 
	  	   //   matcher.group(2) == "4.9" 
	         matcher = pattern.matcher(sx[1]);
	         if (matcher.find()){
	      	   if (matcher.group(1).equals("value")){
	      		   // allocate converted double mValue
	      		   this.mValue[iBr] = Double.parseDouble( matcher.group(2));
	      	   }
	         } else {
	      	   // if this mValue is not valid: 
	      	   // this.mValue[iBr] == 0
	         }
	         iBr++;
	     }
	     return true;
	}
}
